package com.cskaoyan.javase.oop1._10static._6exercise;

/**
 * 启动main方法,先考虑触发类加载,尤其是这个类中有静态成员变量时
 *
 * 首先触发Demo类加载,要想完成Demo类的类加载,于是需要创建Cat对象
 * 要想创建Cat对象,触发Cat类类加载
 * 要想完成Cat类的类加载,需要创建Dog对象
 *
 * 要想创建Dog对象,触发Dog类类加载
 * Dog类中没有静态成员,对程序的输出结果没有影响
 * 直接使用构造器创建对象,于是控制台输出:
 * "dog"
 *
 * Dog对象创建完毕,意味Cat类加载结束
 * 开始创建Cat对象,于是使用构造器,控制台输出:
 * "cat"
 *
 * Cat类创建对象完毕,意味着Demo类类加载结束
 * 于是开始执行main方法,控制台输出:
 * "hello world!"
 *
 * 接下来创建Demo对象,这时三个类都已经类加载完了,无需再次考虑
 *
 * 创建Demo对象,不能立刻执行构造器代码,因为它还有一个Dog对象的成员变量需要完成显式赋值,这时需要创建Dog对象
 * 于是控制台输出:
 * "dog"
 *
 * 最后才执行Demo构造方法,控制台输出:
 * "demo"
 *
 * 类加载相关的知识:
 *     类加载从流程上来说,分为三步:
 *     加载 --> 链接(主要完成类信息的获取) ---> 初始化 (主要用来做和static相关的东西)
 *     一个类的类加载只需要完成前两步,类型信息就已经获取了(JVM已经认识它了),第三步主要是做和static相关的工作.
 *     在这个案例的类加载中：
 *     Demo先走完两步： 加载 --> 链接,完成初始化时发现需要创建Cat对象
 *     Cat走完两步: 加载 ---> 链接,完成初始化时,发现需要创建Dog对象
 *     Dog走完两步: 加载 ---> 链接,完成初始化时,发现需要创建Demo对象,于是直接创建Demo对象,率先完成整个类加载过程
 *
 *     Dog完成后,Cat再完成,Demo最后完成
 *
 *
 * @since 16:30
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    static {
        System.out.println("Demo完成类加载了!");
    }
    static Cat cat = new Cat();  //static int a = 10;

    Dog dog = new Dog();  //int a = 10;
    Dog dog2;

    public static void main(String[] args) {
        System.out.println("hello world!");
        Demo d = new Demo();
    }

    public Demo() {
        System.out.println("demo");
    }
}

class Cat {
    static {
        System.out.println("Cat完成类加载了!");
    }
    static Dog dog = new Dog(); //static3 int a = 10;


    public Cat() {
        System.out.println("cat");
    }
}

class Dog {
    static {
        System.out.println("Dog完成类加载了!");
    }

    static Demo demo = new Demo();

    public Dog() {
        System.out.println("dog");
    }
}